package com.streetsmart;
/**
 *  used to scrape all the html tags to pull business hours data
 */
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.StringTokenizer;

import android.util.Log;

class TimeInstant { 
	int hour;
	int minutes;

	TimeInstant(String intStr, String ampm) {
		if (intStr.contains(":")) {
			String[] splt = intStr.split(":");
			hour = Integer.parseInt(splt[0]);
			minutes = Integer.parseInt(splt[1]);
		}
		else {
			hour  = Integer.parseInt(intStr);
			minutes = 0;
		}
		if (ampm.equalsIgnoreCase("pm")){
			hour += 12;
		}
	}

	TimeInstant(int h, int m){
		hour = h;
		minutes = m;
	}

	@Override
	public String toString() {
		return "TimeInstant [hour=" + hour + ", minutes=" + minutes + "]";
	}

}

class TimeInterval { 
	TimeInstant startInstant;
	TimeInstant endInstant;

	TimeInterval(String stStr, String stAmpm, String endStr, String endAmpm) {
		startInstant = new TimeInstant(stStr, stAmpm);
		endInstant = new TimeInstant(endStr, endAmpm);
	}

	boolean containsTimeInstant(TimeInstant ti){
		if ((ti.hour > startInstant.hour || (ti.hour == startInstant.hour && ti.minutes >= startInstant.minutes)) &&
				(ti.hour < endInstant.hour || (ti.hour == endInstant.hour && ti.minutes <= endInstant.minutes))) {
			return true;
		}
		else 
			return false;			
	}

	@Override
	public String toString() {
		return "TimeInterval [startInstant=" + startInstant
				+ ", endInstant=" + endInstant + "]";
	}
}

public class ScrapeYelp {

	HashMap<Integer,List<TimeInterval>> businessHours = null;

	String yelpBusinessId = "";

	ScrapeYelp(String businessId) {
		yelpBusinessId = businessId;
		businessHours= new HashMap<Integer, List<TimeInterval>>();	
		getBusinessHours();
	}

	/**
	 * Determines whether this business will be open during the interval specified 
	 * @param searchInterval
	 * @return
	 */
	public boolean isBusinessOpen(TimeInstant  searchStartTime, TimeInstant searchEndTime) {
		Calendar cal = Calendar.getInstance();
		int day =  cal.get(Calendar.DAY_OF_WEEK);
		if (businessHours.containsKey(day)){
			for (TimeInterval ti : businessHours.get(day)){
				if (ti.containsTimeInstant(searchStartTime))
				//if (ti.containsTimeInstant(searchStartTime) && ti.containsTimeInstant(searchEndTime))
					return true;
			}

		}
		
		if (businessHours.size() == 0) {
			int hour = cal.get(Calendar.HOUR_OF_DAY);
			// TODO this needs to be fixed later based on categories
			// eg: post office might close at 6pm. but no restaurant will
			if (hour <= 18 && hour >= 11)
				return true;
			else
				return false;
		}
		
		return false;
	}


	private static int getDay(String day) 
	{
		if (day.equalsIgnoreCase("sun"))
			return 0;
		else if (day.equalsIgnoreCase("mon"))
			return 1;
		else if (day.equalsIgnoreCase("tue"))
			return 2;
		else if (day.equalsIgnoreCase("wed"))
			return 3;
		else if (day.equalsIgnoreCase("thu"))
			return 4;
		else if (day.equalsIgnoreCase("fri"))
			return 5;
		else if (day.equalsIgnoreCase("sat"))
			return 6;
		else
			return -1;
	}

	/**
	 * Scrapes the business hours from the yelp page for the business.
	 * This is how its listed in the html.. 
	 * <dd class="attr-BusinessHours"><p class="hours">Mon-Thu, Sun 11 am - 10 pm</p>
	    <p class="hours">Fri-Sat 11 am - 11 pm</p></dd>
	 * @return
	 */
	public HashMap<Integer,List<TimeInterval>> getBusinessHours() {

		final String STARTTAG = "<dd class=\"attr-BusinessHours\">";
		final String ENDTAG = "</dd>";
		//final String STARTTAG = "<span class=\"biz-attr-info flex-box\">";
		//final String ENDTAG = "</span>";
		
		final String HOURS_START_TAG = "<p class=\"hours\">";
		final String HOURS_END_TAG = "</p>";

		long stTime = System.currentTimeMillis();


		try {
			URL yelp = new URL("http://www.yelp.com/biz/"+yelpBusinessId);
			HttpURLConnection connection = (HttpURLConnection) yelp.openConnection(); 
			connection.setRequestMethod("GET");
			connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2");
			
			BufferedReader in = new BufferedReader(
					new InputStreamReader(connection.getInputStream()));

			StringBuilder html = new StringBuilder();

			String inputLine;
			int startTagIndex = -1;
			int searchIndex = 0;

			Log.d("Yelp_html", yelpBusinessId);
			while ((inputLine = in.readLine()) != null){ 
				//Log.d("Yelp_html", inputLine);
				html.append(inputLine.trim());
				// This optimization does seem to help; but not bullet-prood tests. uncomment if needed

				startTagIndex = html.indexOf(STARTTAG, searchIndex);
				if ( startTagIndex !=1 && html.indexOf(ENDTAG, startTagIndex) != -1){
					break;
				}
				searchIndex = html.length() - STARTTAG.length() -1;
				searchIndex = searchIndex < 0 ? 0 : searchIndex;
				
			}
			in.close();
			int stIndex = html.indexOf(STARTTAG);
			if (stIndex != -1){
				int endIndex = html.indexOf(ENDTAG, stIndex);
				String hoursHtml = html.substring(stIndex, endIndex).replaceAll(STARTTAG, "");
				if (hoursHtml.length() <= 0)
					return null;
				hoursHtml = hoursHtml.replaceAll(HOURS_START_TAG, "");
				hoursHtml = hoursHtml.replaceAll(HOURS_END_TAG, "**");

				StringTokenizer strTok = new StringTokenizer(hoursHtml, "**");
				while(strTok.hasMoreTokens()){


					String hourEntry = strTok.nextToken();
					String[] hourEntrySplits = hourEntry.split(" ");
					int sepInd = -1;
					for (int i=0; i < hourEntrySplits.length; i++){
						if (hourEntrySplits[i].equals("-")){
							sepInd = i-2;
							break;
						}
					}

					// hour array has five elements
					TimeInterval ti = new TimeInterval(hourEntrySplits[sepInd], hourEntrySplits[sepInd+1], 
							hourEntrySplits[sepInd+3], hourEntrySplits[sepInd+4]);
					for (int i=0; i< sepInd; i++){
						// the string can be Mon-thu, or Sun formats.
						if (hourEntrySplits[i].contains("-")) {
							hourEntrySplits[i] = hourEntrySplits[i].replaceAll(",", "");
							String[] daysSplit = hourEntrySplits[i].split("-");
							int dayId = getDay(daysSplit[0]);
							while (true){
								if (!businessHours.containsKey(dayId))
									businessHours.put(dayId, new ArrayList<TimeInterval>());
								businessHours.get(dayId).add(ti);
								if (dayId == getDay(daysSplit[1]))
									break;
								dayId = (dayId + 1) % 7;
							}
						}
						else {
							int dayId = getDay(hourEntrySplits[i]);
							if (!businessHours.containsKey(dayId))
								businessHours.put(dayId, new ArrayList<TimeInterval>());
							businessHours.get(dayId).add(ti);
						}
					}		
				}
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}

		//		System.out.println("Complete in "+ (System.currentTimeMillis() - stTime)+" ms");
		return businessHours;
	}


	/**
	 * @param args
	 */
	/*
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		// Open Mon-Thu, Sun 11 am - 10 pm**Fri-Sat 11 am - 11 pm**
		ScrapeYelp y1 = new ScrapeYelp("urban-curry-san-francisco");
		System.out.println(y1.getBusinessHours());
		// try asking for 9 AM - 9:30AM
		System.out.println(y1.isBusinessOpen(new TimeInstant(9, 0), new TimeInstant(9,30)));
		// try asking for 10 PM - 10:30PM, today 
		System.out.println(y1.isBusinessOpen(new TimeInstant(22, 0), new TimeInstant(22,30)));
		// but you can walk in for lunch anyday
		System.out.println(y1.isBusinessOpen(new TimeInstant(13, 0), new TimeInstant(14,0)));

		//ScrapeYelp y2 = new ScrapeYelp("little-delhi-san-francisco");
		//System.out.println(y2.getBusinessHours());


		//getBusinessHours("little-delhi-san-francisco");
		//getBusinessHours("tandoori-mahal-san-francisco-2");

	}*/

}
